package com.hlg.xboot.web.interceptor;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * <p>Description: 拦截器基类</p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company: 中视数讯</p>
 * <p>Site: www.digi-zones.com</p>
 *
 * @author yangxin
 * @version 1.0
 * @date 2016/8/24
 */
public abstract class BaseInterceptor extends HandlerInterceptorAdapter {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    private List<ExcludeUrl> excludeUrls = new ArrayList<>();

    public BaseInterceptor() {
        initExcludeUrls();
    }

    /**
     * 初始化排除过滤的URL
     */
    protected void initExcludeUrls() {
        addExcludeUrl("*","/error");
        addExcludeUrl("*","/resource", true);
    }

    protected void addExcludeUrl(String method,String excludeUrl) {
        excludeUrls.add(new ExcludeUrl(method, excludeUrl));
    }
    protected void addExcludeUrl(String method,String excludeUrl, boolean isLike) {
        excludeUrls.add(new ExcludeUrl(method, excludeUrl, isLike));
    }
    protected void addExcludeUrl(String method,String excludeUrl, boolean isLike, List<String> likeExcludeUrls) {
        excludeUrls.add(new ExcludeUrl(method, excludeUrl, isLike, likeExcludeUrls));
    }
    protected void addExcludeUrl(ExcludeUrl excludeUrl) {
        excludeUrls.add(excludeUrl);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (isExcludeUris(request)) {
            logger.info("exclude uri: {}", request.getRequestURI());
            return true;
        }
        return false;
    }

    /**
     * 是否排除指定的请求
     * @return
     */
    private boolean isExcludeUris(HttpServletRequest request) {
        String uri = request.getRequestURI();
        for (ExcludeUrl excludeUrl : excludeUrls) {
            String method = excludeUrl.getMethod();
            String excludeUri = excludeUrl.getUri();
            if (excludeUrl.isLike()) {
                if (CollectionUtils.isNotEmpty(excludeUrl.getLikeExcludeUrls()) && excludeUrl.getLikeExcludeUrls().contains(uri)) {
                    if (excludeUri.equals(uri) && (method.equals(request.getMethod()) || method.equals("*"))) {
                        return true;
                    }
                } else {
                    if ((uri.startsWith(excludeUri) || uri.endsWith(excludeUri)) &&
                            (method.equals(request.getMethod()) || method.equals("*"))) {
                        return true;
                    }
                }
            } else {
                if (excludeUri.equals(uri) && (method.equals(request.getMethod()) || method.equals("*"))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 打印请求参数
     * @param request
     * @return
     */
    public void printRequestParams(HttpServletRequest request) {
        logger.debug("-------------{} begin-----------", request.getRequestURI());
        Enumeration<String> headers = request.getHeaderNames();
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            logger.debug("请求头：{}={}",header,request.getHeader(header));
        }

        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            logger.debug("请求参数：{}={}", parameterName, request.getParameter(parameterName));
        }
        logger.debug("-------------{} end-----------", request.getRequestURI());
    }

    private final class ExcludeUrl {
        private String method;
        private String uri;
        private boolean isLike;                 // 是否模糊匹配
        private List<String> likeExcludeUrls;   // 模糊匹配排除的url


        public ExcludeUrl(String method, String uri) {
            this.method = method;
            this.uri = uri;
        }

        public ExcludeUrl(String method, String uri, boolean isLike) {
            this.isLike = isLike;
            this.method = method;
            this.uri = uri;
        }

        public ExcludeUrl(String method, String uri, boolean isLike, List<String> likeExcludeUrls) {
            this.method = method;
            this.uri = uri;
            this.isLike = isLike;
            this.likeExcludeUrls = likeExcludeUrls;
        }

        public List<String> getLikeExcludeUrls() {
            return likeExcludeUrls;
        }

        public void setLikeExcludeUrls(List<String> likeExcludeUrls) {
            this.likeExcludeUrls = likeExcludeUrls;
        }

        public boolean isLike() {
            return isLike;
        }

        public void setLike(boolean like) {
            isLike = like;
        }

        public String getMethod() {
            return method;
        }

        public void setMethod(String method) {
            this.method = method;
        }

        public String getUri() {
            return uri;
        }

        public void setUri(String uri) {
            this.uri = uri;
        }
    }
}
